/**
 * @Descrition:
 * @Param:
 * @Param:
 * @Return:
 * @Auditor :ziliang.zhou
 * @Vesion:1.0.0
 */
package com.sunyard.utils.wxv3Util;

import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.net.util.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.UUID;

public class uploadFileTest2 {

    public static void main(String[] args) {

        try {

            //商户号
            String mchid = "1900006031";
            //证书序列号
            String serial_no = "78B864B1837419C54E3F8D69D35C2BC59BDA647C";
            //商户私钥（拷贝apiclient_key.pem文件里-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----之间的内容）
            String rsaPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDALz596tyfxVo0R45Zd86i+YWmnT0FVIo+5nnbN8WoQTYZr3HpbtgBgpOhLEuP2DIIcl0T9qbQZW9NVZeKVlovjsFvLrhfVZ7xC6AeGpZ4C4mIQfirjsOVMz0EeIPmUgZc83d5xnZxAnSw3wsfsQQ1m8MYtfzpoZf70WRAYivZvRhULIj7QcIcVVuQbq3qOUHBQ6NoWlp5GWTy0158xmUZ3DbgWo/01hvzZgTYfSMVBl44ssWqZMSYUWMoWSXCL1N6MWVeJoCeWlG3CxidEQiOygKRIuwxKAX/Yqka2FsUxPCJvylNS3E0a0dj+POLuNNaAWW4mUna+6sqiZhOrBxlAgMBAAECggEAGnZm5G+ycU17Xjd8IlWc3lP9UzPTcyhw4LhbjxPe44wXJvJBfSMGGy8fpNG0ldnvCbq1lkogLhHJgZyHgUTipinB+M02Fep0ODyhj4OZtG3iQiDTXMwLoj+r5zGw98XTmnjrupjZNjZgWvpbTcHSEo+gDYcBjCn0A3iRlUvvPcvOuBschUxPjvmZFqWfC5Qf9nFqbzUljuH9xVroLEtlnMWI5G3hmCevx9JpYWd+wlIUvcNtUFK+E1YIwejART8DWnHoIkrGx6yNt3pvx775XgQlzqj8euRt2j/0Bye2aLFCSv87RhM4UTLCzipY/osKVT/bQ4zCb/huMYxnXjKYAQKBgQDewGyhoRK2dbQS+Io+uqLkIP3HPj85GB0kl8l11Tvly6vJhFJpcQWajmhfbmNUXc2PaGJRVaAv7t1P3K4le5WwM1yI0E0y64JxMxwFCtZ+/qSYicFsTC+i1SNHycIVLDqFNJ0odz1tCLBAUp/yHxy6RPl1o7XvRf2Op4rtpo2RfQKBgQDc3tF5fycxASaAaonyVENtqqxqq+73gXO44oJDOvUcH5M3hDyhzf2rnwck2jB/dWHpmSkazmlkYEJB0m8GO7oTHzFiVe+9vhihwz+qNE56N0CKLRa+bDT2RC6ieg8Ua/RSBTP7PSIIlaEKrDVl8CBimxi3s4aWlvQtehHucOorCQKBgFchR5y1Z59tTQG6rEC7OmonqXzdEVfg4c1lfg0UWniZgVmy45WQ+xMorxTdFgdzJav5tbOA3cbCFVlexdOtkrC4dnKhoADR9FUZG9WxFpPYQUPVZo5ZAq0b19AF0F/9y+o82Vhxw9o5cs/GQgAwQUlvH3Dvl4O/id3aFVK+OlP1AoGBANRQRCB8gBn1NyN+Rjhxk5eZ1r97ouy8vZbd9cXWqMNt/sABF5+aOdx9tApSywfauFIq7n5cKKdaeJZ5SEw/obC77WbPoPNOBrOI0mw0d7O35QxuJ0zJC2gnRoTcvB4vX95wLfW2YD7MRs/Rlkr1NsxStsHvitK7LOGCVDZWyGKxAoGBAJn6crUSlSJtLhp0jqHfciubvA3gdFdM7zendip1pE+OlXQh38hh2s9QXVGReWwEwm+tfJx6SaELTfi5miqSgFOpceAnYX0ZxVNx+WmUd4Fw7FIWUy5KnJ+hSwQv9zFwE9vINafZZdEhGgCJJXdZFEZnlL8HusZvjUim+jc0hJ6I";
            //微信支付平台公钥
            String rsaPublicKeyFile = "";
            //时间戳
            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
            //随机数
            String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");

            //图片文件
            String filePath = "D:\\1.png";//文件路径
            File file = new File(filePath);
            String filename = file.getName();//文件名
            String fileSha256 = DigestUtils.sha256Hex(new FileInputStream(file));//文件sha256

            //拼签名串
            StringBuffer sb = new StringBuffer();
            sb.append("POST").append("\n");
            sb.append("/v3/merchant/media/upload").append("\n");
            sb.append(timestamp).append("\n");
            sb.append(nonce_str).append("\n");
            sb.append("{\"filename\":\"" + filename + "\",\"sha256\":\"" + fileSha256 + "\"}").append("\n");
            System.out.println("签名原串:" + sb.toString());

            //计算签名
            String sign = new String(Base64.encodeBase64(signRSA(sb.toString(), rsaPrivateKey)));
            System.out.println("签名sign值:" + sign);

            //拼装http头的Authorization内容
            String authorization = "WECHATPAY2-SHA256-RSA2048 mchid=\"" + mchid + "\",nonce_str=\"" + nonce_str + "\",signature=\"" + sign + "\",timestamp=\"" + timestamp + "\",serial_no=\"" + serial_no + "\"";
            System.out.println("authorization值:" + authorization);

            //接口URL
            String url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload";
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);

            //设置头部
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-Type", "multipart/form-data");
            httpPost.addHeader("Authorization", authorization);

            //创建MultipartEntityBuilder
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            //设置boundary
            multipartEntityBuilder.setBoundary("boundary");
            multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));
            //设置meta内容
            multipartEntityBuilder.addTextBody("meta", "{\"filename\":\"" + filename + "\",\"sha256\":\"" + fileSha256 + "\"}", ContentType.APPLICATION_JSON);
            //设置图片内容
            multipartEntityBuilder.addBinaryBody("file", file, ContentType.create("image/jpg"), filename);
            //放入内容
            httpPost.setEntity(multipartEntityBuilder.build());

            //获取返回内容
            CloseableHttpResponse response = httpclient.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            String rescontent = new String(InputStreamTOByte(httpEntity.getContent()));
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(rescontent);
            System.out.println("返回内容:" + rescontent);
            //获取返回的http header
            Header headers[] = response.getAllHeaders();
            int i = 0;
            while (i < headers.length) {
                System.out.println(headers[i].getName() + ":  " + headers[i].getValue());
                i++;
            }

           /* //验证微信支付返回签名
            String Wtimestamp = response.getHeaders("Wechatpay-Timestamp")[0].getValue();
            String Wnonce = response.getHeaders("Wechatpay-Nonce")[0].getValue();
            String Wsign = response.getHeaders("Wechatpay-Signature")[0].getValue();
            //拼装待签名串
            StringBuffer ss =new StringBuffer();
            ss.append(Wtimestamp).append("\n");
            ss.append(Wnonce).append("\n");
            ss.append(rescontent).append("\n");*/
            //验证签名
           /* if(verifyRSA(ss.toString(), Base64.decodeBase64(Wsign.getBytes()), rsaPublicKeyFile)) {
                System.out.println("签名验证成功");
            }else {
                System.out.println("签名验证失败");
            }*/

            EntityUtils.consume(httpEntity);
            response.close();
            if (200 == response.getStatusLine().getStatusCode()) {
                //return jsonObject.getString("media_id");
            } else {
                //return jsonObject.getString("message");
            }
        } catch (Exception e) {
            System.out.println("发送POST请求异常！" + e);
            e.printStackTrace();
        }

    }

    public static byte[] InputStreamTOByte(InputStream in) throws IOException {

        int BUFFER_SIZE = 4096;
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[BUFFER_SIZE];
        int count = -1;

        while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)
            outStream.write(data, 0, count);

        data = null;
        byte[] outByte = outStream.toByteArray();
        outStream.close();

        return outByte;
    }


    public static byte[] signRSA(String data, String priKey) throws Exception {


        //签名的类型

        Signature sign = Signature.getInstance("SHA256withRSA");

        //读取商户私钥,该方法传入商户私钥证书的内容即可

        byte[] keyBytes = Base64.decodeBase64(priKey);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        sign.initSign(privateKey);

        sign.update(data.getBytes("UTF-8"));

        return sign.sign();

    }


    public static boolean verifyRSA(String data, byte[] sign, String pubKey) throws Exception {

        if (data == null || sign == null || pubKey == null) {

            return false;

        }


        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        FileInputStream in = new FileInputStream(pubKey);

        Certificate c = cf.generateCertificate(in);

        in.close();

        PublicKey publicKey = c.getPublicKey();

        Signature signature = Signature.getInstance("SHA256WithRSA");

        signature.initVerify(publicKey);

        signature.update(data.getBytes("UTF-8"));

        return signature.verify(sign);

    }

}
